<!DOCTYPE html>
<html lang="zh-Hans">
<head>

    <!--[if lt IE 9]>
        <style>body {display: none; background: none !important} </style>
        <meta http-equiv="Refresh" Content="0; url=//outdatedbrowser.com/" />
    <![endif]-->

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="format-detection" content="telephone=no" />
<meta name="author" content="王诗翔" />



<meta name="description" content="条件控制 内容  使用if-then语句 嵌套if语句 test命令 复合条件测试 使用双方括号和双括号 case命令   许多程序要求对shell脚本中的命令施加一些逻辑流程控制。而某些命令会根据条件判断执行相应的命令，这样的命令通常叫做结构化命令。从概念上理解，结构化命令是shell脚本的逻辑结构，不像顺序执行shell脚本，而是有组织地执行命令以应对复杂任务需求。 if-then语句最基本">
<meta name="keywords" content="bash shell,shell笔记">
<meta property="og:type" content="article">
<meta property="og:title" content="Linux结构化命令">
<meta property="og:url" content="https://shixiangwang.github.io/2017/08/11/structural-command-of-shell/index.html">
<meta property="og:site_name" content="Cloudberry">
<meta property="og:description" content="条件控制 内容  使用if-then语句 嵌套if语句 test命令 复合条件测试 使用双方括号和双括号 case命令   许多程序要求对shell脚本中的命令施加一些逻辑流程控制。而某些命令会根据条件判断执行相应的命令，这样的命令通常叫做结构化命令。从概念上理解，结构化命令是shell脚本的逻辑结构，不像顺序执行shell脚本，而是有组织地执行命令以应对复杂任务需求。 if-then语句最基本">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2018-01-27T04:08:05.774Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Linux结构化命令">
<meta name="twitter:description" content="条件控制 内容  使用if-then语句 嵌套if语句 test命令 复合条件测试 使用双方括号和双括号 case命令   许多程序要求对shell脚本中的命令施加一些逻辑流程控制。而某些命令会根据条件判断执行相应的命令，这样的命令通常叫做结构化命令。从概念上理解，结构化命令是shell脚本的逻辑结构，不像顺序执行shell脚本，而是有组织地执行命令以应对复杂任务需求。 if-then语句最基本">

<link rel="apple-touch-icon" href= "/apple-touch-icon.png">


    <link rel="alternate" href="/atom.xml" title="Cloudberry" type="application/atom+xml">



    <link rel="shortcut icon" href="/favicon.png">



    <link href="//cdn.bootcss.com/animate.css/3.5.1/animate.min.css" rel="stylesheet">



    <link href="//cdn.bootcss.com/fancybox/2.1.5/jquery.fancybox.min.css" rel="stylesheet">



    <script src="//cdn.bootcss.com/pace/1.0.2/pace.min.js"></script>
    <link href="//cdn.bootcss.com/pace/1.0.2/themes/blue/pace-theme-minimal.css" rel="stylesheet">


<link rel="stylesheet" href="../../../../css/style.css">



<link href="//cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">


<title>Linux结构化命令 | Cloudberry</title>

<script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<script src="//cdn.bootcss.com/clipboard.js/1.5.10/clipboard.min.js"></script>

<script>
    var yiliaConfig = {
        fancybox: true,
        animate: true,
        isHome: false,
        isPost: true,
        isArchive: false,
        isTag: false,
        isCategory: false,
        fancybox_js: "//cdn.bootcss.com/fancybox/2.1.5/jquery.fancybox.min.js",
        scrollreveal: "//cdn.bootcss.com/scrollReveal.js/3.1.4/scrollreveal.min.js",
        search: true
    }
</script>


    <script>
        yiliaConfig.jquery_ui = [true, "//cdn.bootcss.com/jqueryui/1.10.4/jquery-ui.min.js", "//cdn.bootcss.com/jqueryui/1.10.4/css/jquery-ui.min.css"];
    </script>



    <script> yiliaConfig.rootUrl = "\/";</script>






</head>
<body>
  <div id="container">
    <div class="left-col">
    <div class="overlay"></div>
<div class="intrude-less">
    <header id="header" class="inner">
        <a href="/" class="profilepic">
            <img src="/img/avatar.png" class="animated zoomIn">
        </a>
        <hgroup>
          <h1 class="header-author"><a href="/">王诗翔</a></h1>
        </hgroup>

        
        <p class="header-subtitle">A site for writing life</p>
        

        
            <form id="search-form">
            <input type="text" id="local-search-input" name="q" placeholder="search..." class="search form-control" autocomplete="off" autocorrect="off" searchonload="false" />
            <i class="fa fa-times" onclick="resetSearch()"></i>
            </form>
            <div id="local-search-result"></div>
            <p class='no-result'>No results found <i class='fa fa-spinner fa-pulse'></i></p>
        


        
            <div id="switch-btn" class="switch-btn">
                <div class="icon">
                    <div class="icon-ctn">
                        <div class="icon-wrap icon-house" data-idx="0">
                            <div class="birdhouse"></div>
                            <div class="birdhouse_holes"></div>
                        </div>
                        <div class="icon-wrap icon-ribbon hide" data-idx="1">
                            <div class="ribbon"></div>
                        </div>
                        
                        <div class="icon-wrap icon-link hide" data-idx="2">
                            <div class="loopback_l"></div>
                            <div class="loopback_r"></div>
                        </div>
                        
                        
                        <div class="icon-wrap icon-me hide" data-idx="3">
                            <div class="user"></div>
                            <div class="shoulder"></div>
                        </div>
                        
                    </div>
                    
                </div>
                <div class="tips-box hide">
                    <div class="tips-arrow"></div>
                    <ul class="tips-inner">
                        <li>菜单</li>
                        <li>标签</li>
                        
                        <li>友情链接</li>
                        
                        
                        <li>关于我</li>
                        
                    </ul>
                </div>
            </div>
        

        <div id="switch-area" class="switch-area">
            <div class="switch-wrap">
                <section class="switch-part switch-part1">
                    <nav class="header-menu">
                        <ul>
                        
                            <li><a href="../../../../index.html">主页</a></li>
                        
                            <li><a href="../../../../archives/">所有文章</a></li>
                        
                            <li><a href="../../../../tags/">标签云</a></li>
                        
                            <li><a href="../../../../about/">关于我</a></li>
                        
                        </ul>
                    </nav>
                    <nav class="header-nav">
                        <ul class="social">
                            
                                <a class="fa Email" href="mailto:w_shixiang@163.com" title="Email"></a>
                            
                                <a class="fa GitHub" href="https://github.com/ShixiangWang" title="GitHub"></a>
                            
                                <a class="fa RSS" href="../../../../atom.xml" title="RSS"></a>
                            
                                <a class="fa 知乎" href="https://www.zhihu.com/people/wang-shi-xiang-65/activities" title="知乎"></a>
                            
                                <a class="fa 简书" href="https://www.jianshu.com/u/b6608e27dc74" title="简书"></a>
                            
                                <a class="fa Twitter" href="https://twitter.com/WangShxiang" title="Twitter"></a>
                            
                        </ul>
                    </nav>
                </section>
                
                
                <section class="switch-part switch-part2">
                    <div class="widget tagcloud" id="js-tagcloud">
                        <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Gist/">Gist</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Linux-shell/">Linux shell</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/OOP/">OOP</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/R/">R</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Rmarkdown/">Rmarkdown</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Rmd/">Rmd</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Rstudio/">Rstudio</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/bash-shell/">bash shell</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/fasta/">fasta</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/git/">git</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/github/">github</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/lapply/">lapply</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/linux/">linux</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/markdown/">markdown</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/md/">md</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/python/">python</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/sapply/">sapply</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/sed/">sed</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/shell笔记/">shell笔记</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/survival/">survival</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/survminer/">survminer</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/vapply/">vapply</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/写作/">写作</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/数据处理/">数据处理</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/文本处理/">文本处理</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/生存分析/">生存分析</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/生物信息学/">生物信息学</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/类/">类</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/迭代计算/">迭代计算</a></li></ul>
                    </div>
                </section>
                
                
                
                <section class="switch-part switch-part3">
                    <div id="js-friends">
                    
                      <a class="main-nav-link switch-friends-link" href="http://www.ruanyifeng.com/blog/archives.html">阮一峰的网络日志</a>
                    
                      <a class="main-nav-link switch-friends-link" href="http://blog.fens.me/series-r/">R的极客理想系列</a>
                    
                      <a class="main-nav-link switch-friends-link" href="https://yihui.name/">谢益辉</a>
                    
                      <a class="main-nav-link switch-friends-link" href="http://www.huangshujia.me/">解螺旋的矿工</a>
                    
                      <a class="main-nav-link switch-friends-link" href="https://github.com/GuangchuangYu">GuangchuangYu</a>
                    
                      <a class="main-nav-link switch-friends-link" href="https://vip.biotrainee.com/">生信技能树</a>
                    
                    </div>
                </section>
                

                
                
                <section class="switch-part switch-part4">
                
                    <div id="js-aboutme">人该是自己生活的主宰，而不是别人手中的行货</div>
                </section>
                
            </div>
        </div>
    </header>                
</div>
    </div>
    <div class="mid-col">
      <nav id="mobile-nav">
      <div class="overlay">
          <div class="slider-trigger"></div>
          <h1 class="header-author js-mobile-header hide"><a href="/" title="回到主页">王诗翔</a></h1>
      </div>
    <div class="intrude-less">
        <header id="header" class="inner">
            <a href="/" class="profilepic">
                <img src="/img/avatar.png" class="animated zoomIn">
            </a>
            <hgroup>
              <h1 class="header-author"><a href="/" title="回到主页">王诗翔</a></h1>
            </hgroup>
            
            <p class="header-subtitle">A site for writing life</p>
            
            <nav class="header-menu">
                <ul>
                
                    <li><a href="../../../../index.html">主页</a></li>
                
                    <li><a href="../../../../archives/">所有文章</a></li>
                
                    <li><a href="../../../../tags/">标签云</a></li>
                
                    <li><a href="../../../../about/">关于我</a></li>
                
                <div class="clearfix"></div>
                </ul>
            </nav>
            <nav class="header-nav">
                        <ul class="social">
                            
                                <a class="fa Email" target="_blank" href="mailto:w_shixiang@163.com" title="Email"></a>
                            
                                <a class="fa GitHub" target="_blank" href="https://github.com/ShixiangWang" title="GitHub"></a>
                            
                                <a class="fa RSS" target="_blank" href="../../../../atom.xml" title="RSS"></a>
                            
                                <a class="fa 知乎" target="_blank" href="https://www.zhihu.com/people/wang-shi-xiang-65/activities" title="知乎"></a>
                            
                                <a class="fa 简书" target="_blank" href="https://www.jianshu.com/u/b6608e27dc74" title="简书"></a>
                            
                                <a class="fa Twitter" target="_blank" href="https://twitter.com/WangShxiang" title="Twitter"></a>
                            
                        </ul>
            </nav>
        </header>                
    </div>
    <link class="menu-list" tags="标签" friends="友情链接" about="关于我"/>
</nav>
      <div class="body-wrap"><article id="post-structural-command-of-shell" class="article article-type-post" itemscope itemprop="blogPost">
  
    <div class="article-meta">
      <a href="" class="article-date">
      <time datetime="2017-08-10T16:00:00.000Z" itemprop="datePublished">2017-08-11</time>
</a>


    </div>
  
  <div class="article-inner">
    
      <input type="hidden" class="isFancy" />
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      Linux结构化命令
    </h1>
  

      </header>
      
      <div class="article-info article-info-post">
        
    <div class="article-category tagcloud">
    <a class="article-category-link" href="../../../../categories/Linux杂烩/">Linux杂烩</a><a class="article-category-link" href="../../../../categories/Linux杂烩/shell编程/">shell编程</a>
    </div>


        
    <div class="article-tag tagcloud">
        <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="../../../../tags/bash-shell/">bash shell</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="../../../../tags/shell笔记/">shell笔记</a></li></ul>
    </div>

        <div class="clearfix"></div>
      </div>
      
    
    <div class="article-entry" itemprop="articleBody">
      
          
        <a id="more"></a>
<h2 id="条件控制"><a href="#条件控制" class="headerlink" title="条件控制"></a>条件控制</h2><blockquote>
<p><strong>内容</strong></p>
<ul>
<li>使用if-then语句</li>
<li>嵌套if语句</li>
<li>test命令</li>
<li>复合条件测试</li>
<li>使用双方括号和双括号</li>
<li>case命令</li>
</ul>
</blockquote>
<p>许多程序要求对shell脚本中的命令施加一些逻辑流程控制。而某些命令会根据条件判断执行相应的命令，这样的命令通常叫做<strong>结构化命令</strong>。从概念上理解，结构化命令是shell脚本的逻辑结构，不像顺序执行shell脚本，而是有组织地执行命令以应对复杂任务需求。</p>
<h3 id="if-then语句"><a href="#if-then语句" class="headerlink" title="if-then语句"></a>if-then语句</h3><p>最基本的结构化命令是if-then语句，它的格式如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">if command</span><br><span class="line">then</span><br><span class="line">truecommands</span><br><span class="line">fi</span><br></pre></td></tr></table></figure>
<p><strong>注意</strong>，在其他编程语言中，<code>if</code>语句之后的对象是一个等式，等式的结果为<code>TRUE</code>或者<code>FALSE</code>，但是bash shell中的<code>if</code>语句是运行<code>if</code>后面的命令，如果该命令的退出状态码是0（命令成功执行），则运行<code>then</code>语句后面的命令。<code>fi</code>表示<code>if</code>语句到此结束。</p>
<p>下面是一个简单的例子：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test1.sh</span><br><span class="line"><span class="meta">#</span><span class="bash">! /bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> testing the <span class="keyword">if</span> statement</span></span><br><span class="line">if pwd</span><br><span class="line">then</span><br><span class="line">    echo "It worked"</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ chmod u+x test1.sh</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test1.sh</span><br><span class="line">/home/wsx/script_learn</span><br><span class="line">It worked</span><br></pre></td></tr></table></figure>
<p>这个例子中在判断成功执行<code>pwd</code>命令后，执行输出文本字符串。</p>
<p>大家可以尝试把<code>pwd</code>命令改成随便乱打的字符试试结果。它会显示报错信息，<code>then</code>后面的语句也不会执行。</p>
<p>if-then语句的另一种形式：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if command; then</span><br><span class="line">commands</span><br><span class="line">fi</span><br></pre></td></tr></table></figure>
<p>在then部分，我们可以使用多个命令（从格式中command结尾有没有s也可以看出）。</p>
<p>我们再来一个例子：在<code>if</code>语句中用<code>grep</code>命令在<code>/etc/passwd</code>文件中查找某个用户名当前是否在系统上使用。如果有用户使用了哪个登录名，脚本会显示一些文本信息并列出该用户HOME目录的bash文件。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test3.sh</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> testing multiple commands <span class="keyword">in</span> the <span class="keyword">then</span> section</span></span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">testuser=wsx</span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">if grep $testuser /etc/passwd</span><br><span class="line">then</span><br><span class="line">  echo "This is my first command"</span><br><span class="line">  echo "This is my second command"</span><br><span class="line">  echo "I can even put in other commands besides echo:"</span><br><span class="line">  ls -a /home/$testuser/.b*</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ chmod u+x test3.sh</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test3.sh</span><br><span class="line">wsx:x:1000:1000:wsx,,,:/home/wsx:/bin/bash</span><br><span class="line">This is my first command</span><br><span class="line">This is my second command</span><br><span class="line">I can even put in other commands besides echo:</span><br><span class="line">/home/wsx/.bash_history  /home/wsx/.bashrc</span><br><span class="line">/home/wsx/.bash_logout	 /home/wsx/.bashrc-anaconda3.bak</span><br></pre></td></tr></table></figure>
<p>如果设置的用户名不存在，那么就没有输出。那么如果在这里显示的一些消息可以说明用户名在系统中未找到，这样可能就会显得更友好。所以接下来看看<code>if-then-else</code>语句。</p>
<h3 id="if-then-else语句"><a href="#if-then-else语句" class="headerlink" title="if-then-else语句"></a>if-then-else语句</h3><p>我相信意思非常容易理解，这里较之前我们添加了一个<code>else</code>块来处理<code>if</code>中命令没有成功执行的步骤。格式为：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">if command</span><br><span class="line">then</span><br><span class="line">  commands</span><br><span class="line">else commands</span><br><span class="line">fi</span><br></pre></td></tr></table></figure>
<h3 id="嵌套if"><a href="#嵌套if" class="headerlink" title="嵌套if"></a>嵌套if</h3><p>有时我们需要检查脚本代码中的多种条件，可以是用嵌套的<code>if-then</code>语句。</p>
<p>处理一个例子：检查<code>/etc/passwd</code>文件中是否存在某个用户名以及该用户名的目录是否存在。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test5.sh</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> Testing nested ifs</span></span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">testuser=NoSuchUser</span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">if grep $testuser /etc/passwd</span><br><span class="line">then</span><br><span class="line">  echo "The user $testuser exits on this system."</span><br><span class="line">else</span><br><span class="line">  echo "The user $testuser does not exit on this system."</span><br><span class="line">  if ls -d /home/$testuser/</span><br><span class="line">  then</span><br><span class="line">     echo "However, $testuser has a directory."</span><br><span class="line">  fi</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ chmod u+x test5.sh</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test5.sh</span><br><span class="line">The user NoSuchUser does not exit on this system.</span><br><span class="line">ls: 无法访问'/home/NoSuchUser/': 没有那个文件或目录</span><br></pre></td></tr></table></figure>
<p>可以使用<code>else</code>部分的另一种形式:<code>elif</code>。这样我们就不再用书写多个<code>if-then</code>语句了。在其他语言中，有的是用<code>elif</code>的形式，有的使用<code>else if</code>等形式。面对相同内含在不同语言中不同的表示方式，我们需要有意识地区别，以免接触的东西多了可能各种语言代码串写喔。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">if command1</span><br><span class="line">then</span><br><span class="line">truecommands</span><br><span class="line">elif command2</span><br><span class="line">then</span><br><span class="line">truemore commands</span><br><span class="line">fi</span><br></pre></td></tr></table></figure>
<p>这种表示方式逻辑更为清晰，但是也有点容易让写的人搞混。其实可以看到一个<code>if</code>对应一个<code>fi</code>。这是一个大的嵌套<code>if</code>结构。</p>
<p><strong>记住</strong>，在<code>elif</code>语句中，紧跟其后的<code>else</code>语句属于<code>elif</code>代码块，而不是属于<code>if-then</code>代码块。</p>
<h3 id="test命令"><a href="#test命令" class="headerlink" title="test命令"></a>test命令</h3><p>到此为止，我们很清楚<code>if</code>后面跟着的是普通的shell命令，那么我们需要测试其他条件怎么办呢？</p>
<p><code>test</code>命令提供了在<code>if-then</code>语句中测试不同条件的途径。如果<code>test</code>命令中列出的条件成立，<code>test</code>命令就会退出并返回状态码0。这样<code>if-then</code>语句就与其他编程语言中的<code>if-then</code>语句以类似的方式工作了。</p>
<p>test命令格式：</p>
<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">test </span>condition</span><br></pre></td></tr></table></figure>
<p><code>condition</code>是<code>test</code>命令要测试的一系列参数和值。如果不写这个<code>condition</code>，<code>test</code>返回非0，<code>if</code>语句跳转到<code>else</code>进行执行。</p>
<p>bash shell提供了一种条件测试方法，无需在<code>if-then</code>语句中声明<code>test</code>命令。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if [ condition ]</span><br><span class="line">then commands</span><br><span class="line">fi</span><br></pre></td></tr></table></figure>
<p>这跟我们其他的编程习惯非常接近。建议使用这种方式。</p>
<p>如果使用<code>test</code>命令，需要记住的是各种条件参数。</p>
<p><strong>数值比较</strong></p>
<table>
<thead>
<tr>
<th>比较</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>n1 -eq n2</td>
<td>(n1)等于(n2)</td>
</tr>
<tr>
<td>n1 -ge n2</td>
<td>大于或等于</td>
</tr>
<tr>
<td>n1 -gt n2</td>
<td>大于</td>
</tr>
<tr>
<td>n1 -le n2</td>
<td>小于或等于</td>
</tr>
<tr>
<td>n1 -lt n2</td>
<td>小于</td>
</tr>
<tr>
<td>n1 -ne n2</td>
<td>不等于</td>
</tr>
</tbody>
</table>
<p><strong>字符串比较</strong></p>
<table>
<thead>
<tr>
<th>比较</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>str1 = str2</td>
<td>（str1与str2比较）相同</td>
</tr>
<tr>
<td>str1 != str2</td>
<td>不同</td>
</tr>
<tr>
<td>str1 &lt; str2</td>
<td>小</td>
</tr>
<tr>
<td>str1 &gt; str2</td>
<td>大</td>
</tr>
<tr>
<td>-n str1</td>
<td>检查string1的长度非0</td>
</tr>
<tr>
<td>-z str1</td>
<td>检查string1的长度是否为0</td>
</tr>
</tbody>
</table>
<p>注意，大于和小于号必须转义；大于和小于顺序和sort命令所采用的不同。</p>
<p><strong>文件比较</strong></p>
<table>
<thead>
<tr>
<th>比较</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>-d file</td>
<td>检查file是否存在并是一个目录</td>
</tr>
<tr>
<td>-e file</td>
<td>～是否存在</td>
</tr>
<tr>
<td>-f file</td>
<td>～是否存在并是一个文件</td>
</tr>
<tr>
<td>-r file</td>
<td>～是否存在并可读</td>
</tr>
<tr>
<td>-s file</td>
<td>～是否存在并非空</td>
</tr>
<tr>
<td>-w file</td>
<td>～是否存在并可写</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td>-x file</td>
<td>～是否存在并可执行</td>
</tr>
<tr>
<td>-O file</td>
<td>～是否存在并属当前用户所有</td>
</tr>
<tr>
<td>-G file</td>
<td>～是否存在并且默认组与当前用户相同</td>
</tr>
<tr>
<td>file1 -nt file2</td>
<td>检查file1是否比file2新</td>
</tr>
<tr>
<td>file1 -ot file2</td>
<td>检查file1是否比file2旧</td>
</tr>
</tbody>
</table>
<h3 id="复合条件测试"><a href="#复合条件测试" class="headerlink" title="复合条件测试"></a>复合条件测试</h3><p><code>if-then</code>语句允许我们使用布尔逻辑来组合测试。可用</p>
<ul>
<li>[ condition1] &amp;&amp; [ condition2]</li>
<li><code>[ condition1] || [ condition2]</code></li>
</ul>
<h3 id="if-then的高级特性"><a href="#if-then的高级特性" class="headerlink" title="if-then的高级特性"></a>if-then的高级特性</h3><ul>
<li>用于数学表达式的双括号</li>
<li>用于高级字符串处理功能的双方括号</li>
</ul>
<p><strong>双括号</strong></p>
<p>命令格式：</p>
<figure class="highlight lisp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(( <span class="name">expresiion</span> ))</span><br></pre></td></tr></table></figure>
<p><code>expression</code>可以是任意的数学赋值或比较表达式。除了<code>test</code>命令使用的标准数学运算符，下面列出了一些其他的：</p>
<table>
<thead>
<tr>
<th>符号</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>val ++</td>
<td>后增</td>
</tr>
<tr>
<td>val –</td>
<td>后减</td>
</tr>
<tr>
<td>++ val</td>
<td>先增</td>
</tr>
<tr>
<td>– val</td>
<td>先减</td>
</tr>
<tr>
<td>!</td>
<td>逻辑取反</td>
</tr>
<tr>
<td>~</td>
<td>位求反</td>
</tr>
<tr>
<td>**</td>
<td>幂运算</td>
</tr>
<tr>
<td>&lt;&lt;</td>
<td>左位移</td>
</tr>
<tr>
<td>&gt;&gt;</td>
<td>右位移</td>
</tr>
<tr>
<td>&amp;</td>
<td>位布尔和</td>
</tr>
<tr>
<td>\</td>
<td></td>
<td>位布尔或</td>
</tr>
<tr>
<td>&amp;&amp;</td>
<td>逻辑和</td>
</tr>
<tr>
<td>\</td>
<td>\</td>
<td></td>
<td>逻辑或</td>
</tr>
</tbody>
</table>
<p>看一个例子：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test23.sh</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> using doble parenthesis</span></span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">val1=10</span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">if (( $val1 ** 2 &gt; 90 ))</span><br><span class="line">then</span><br><span class="line">  (( val2 = $val1 ** 2 ))</span><br><span class="line">  echo "The square of $val1 is $val2"</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ chmod u+x test23.sh</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test23.sh</span><br><span class="line">The square of 10 is 100</span><br></pre></td></tr></table></figure>
<p><strong>双方括号</strong></p>
<p>双方括号命令提供了针对字符串比较的高级特性。命令格式如下：</p>
<figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">[[ expression ]]</span></span><br></pre></td></tr></table></figure>
<p>双方括号里的<code>expression</code>使用了<code>test</code>命令中采用的标准字符串比较。但它提供了<code>test</code>没有提供的一个特性——模式匹配。</p>
<p>在模式匹配中，可以定义一个正则表达式来匹配字符串值。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test24.sh</span><br><span class="line"><span class="meta">#</span><span class="bash">! /bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> using pattern matching</span></span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">if [[ $USER == r* ]]</span><br><span class="line">then</span><br><span class="line">  echo "Hello $USER"</span><br><span class="line">else</span><br><span class="line">  echo "Sorry, I do not know you"</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ chmod u+x test24.sh</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test24.sh</span><br><span class="line">Sorry, I do not know you</span><br></pre></td></tr></table></figure>
<p>上面一个脚本中，我们使用了双等号。双等号将右边的字符串视为一个模式，并将其应用模式匹配规则。</p>
<h3 id="case命令"><a href="#case命令" class="headerlink" title="case命令"></a>case命令</h3><p>有了<code>case</code>命令，就不需要写出所有的<code>elif</code>语句来不停地检查同一个变量的值了。<code>case</code>命令会采用列表格式来检查单个变量的多值。</p>
<p>下面是两个脚本实现相同功能进行对比：</p>
<p>if语句：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test25.sh</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> looking <span class="keyword">for</span> a possible value</span></span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">if [ $USER = "rich" ]</span><br><span class="line">then</span><br><span class="line">  echo "Welcome $USER"</span><br><span class="line">  echo "Please enjoy you visit"</span><br><span class="line">elif [ $USER = "barbara" ]</span><br><span class="line">then</span><br><span class="line">  echo "Welcome $USER"</span><br><span class="line">  echo "Please enjoy you visit"</span><br><span class="line">elif [ $USER = "testing" ]</span><br><span class="line">then</span><br><span class="line">  echo "Special testing account"</span><br><span class="line">elif [ $USER = "jessica" ]</span><br><span class="line">then</span><br><span class="line">  echo "Do not forget to logout when you're done"</span><br></pre></td></tr></table></figure>
<p>case语句：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">case variable <span class="keyword">in</span></span><br><span class="line">pattern1 | pattern2) commands1;;</span><br><span class="line">pattern3) commands2;;</span><br><span class="line">*)<span class="built_in"> default </span>commands;;</span><br><span class="line">esac</span><br></pre></td></tr></table></figure>
<p>上面的实例可以用<code>case</code>语句表示为：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test26.sh</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> using the <span class="keyword">case</span> <span class="built_in">command</span></span></span><br><span class="line"><span class="meta">#</span><span class="bash"></span></span><br><span class="line">case $USER in</span><br><span class="line">rich | barbara)</span><br><span class="line">  echo "Welcome, $USER"</span><br><span class="line">  echo "Please enjoy your visits";;</span><br><span class="line">testing)</span><br><span class="line">  echo "Special testing account";;</span><br><span class="line">jessica)</span><br><span class="line">  echo "Do not forget to log off whe you're done";;</span><br><span class="line">*)</span><br><span class="line">  echo "Sorry, you are not allowed here";;</span><br><span class="line">esac</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ chmod u+x test26.sh</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test26.sh</span><br><span class="line">Sorry, you are not allowed here</span><br></pre></td></tr></table></figure>
<p><code>case</code>命令会将指定的变量与不同模式进行比较。如果变量和模式是匹配的，那么shell会执行为该模式指定的命令。可以通过竖线操作符在一行中分隔出多个模式。星号会捕获所有与已知模式不匹配的值。注意双分号的使用。</p>
<h3 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h3><blockquote>
<p>最基本的命令是<code>if-then</code>语句；</p>
<p>可以拓展<code>if-then</code>语句为<code>if-then-else</code>语句；</p>
<p>可以将<code>if-then-else</code>语句通过<code>elif</code>语句连接起来；</p>
<p>在脚本中，我们需要测试一种条件而不是命令时，比如数值、字符串内容、文件或目录的状态，<code>test</code>命令提供了简单方法；</p>
<p>方括号是<code>test</code>命令统一的特殊bash命令；</p>
<p>双括号使用另一种操作符进行高级数学运算双方括号允许高级字符串模式匹配运算；</p>
<p><code>case</code>命令是执行多个<code>if-then-else</code>命令的简便方式，它会参照一个值列表来检查单个变量的值。</p>
</blockquote>
<p>关于结构化命令中循环，将在下次整理的笔记中阐述。</p>
<h2 id="循环控制"><a href="#循环控制" class="headerlink" title="循环控制"></a>循环控制</h2><blockquote>
<p><strong>内容</strong></p>
<ul>
<li>for循环语句</li>
<li>until迭代语句使用while语句</li>
<li>循环</li>
<li>重定向循环的输出</li>
</ul>
</blockquote>
<p>这一节我们来了解如何重复一些过程和命令，也就是循环执行一组命令直到达到了某个特定条件。</p>
<h3 id="for命令"><a href="#for命令" class="headerlink" title="for命令"></a>for命令</h3><p>基本格式：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for var in list</span><br><span class="line">do</span><br><span class="line">truecommands</span><br><span class="line">done</span><br></pre></td></tr></table></figure>
<p>也可以</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">for var in list; do</span><br></pre></td></tr></table></figure>
<p>分号只用来分隔命令的，让代码更简约。</p>
<p>来个简单例子：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test1</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> basic <span class="keyword">for</span> <span class="built_in">command</span></span></span><br><span class="line"></span><br><span class="line">for test in Alabama Alaska Arizona Arkansas California Colorado</span><br><span class="line">do</span><br><span class="line">    echo The next state is $test</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test1</span><br><span class="line">The next state is Alabama</span><br><span class="line">The next state is Alaska</span><br><span class="line">The next state is Arizona</span><br><span class="line">The next state is Arkansas</span><br><span class="line">The next state is California</span><br><span class="line">The next state is Colorado</span><br></pre></td></tr></table></figure>
<p>这里操作基本和其他语言一致（格式不同），不多讲啦。</p>
<p><strong>在读取列表中的复杂值时</strong>，我们可能会遇到问题。比如下面这个例子：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat badtest1</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> another example of how not to use the <span class="keyword">for</span> <span class="built_in">command</span></span></span><br><span class="line"></span><br><span class="line">for test in I don't know if this'll work</span><br><span class="line">do</span><br><span class="line">    echo "word:$test"</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./badtest1</span><br><span class="line">word:I</span><br><span class="line">word:dont know if thisll</span><br><span class="line">word:work</span><br></pre></td></tr></table></figure>
<p>我们可以看到shell看到了列表值中的单引号尝试使用它们来定义一个单独的数据值。</p>
<p>这里有两种解决办法：</p>
<ul>
<li>使用转义字符将单引号转义</li>
<li>使用双引号来定义用到单引号的值</li>
</ul>
<p>我们将这两种解决办法同时用到上个例子：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test2</span><br><span class="line"><span class="meta">#</span><span class="bash">! /bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> another example of how not to use the <span class="keyword">for</span> <span class="built_in">command</span></span></span><br><span class="line"></span><br><span class="line">for test in I don\'t know if "this'll" work; do</span><br><span class="line">echo  "word:$test"</span><br><span class="line">done</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test2</span><br><span class="line">word:I</span><br><span class="line">word:don't</span><br><span class="line">word:know</span><br><span class="line">word:if</span><br><span class="line">word:this'll</span><br><span class="line">word:work</span><br></pre></td></tr></table></figure>
<p>我们可能明白了<code>for</code>循环是假定每个值是用空格分隔的，所以当有包含空格的数据时，我们需要用双引号括起来。</p>
<p><strong>通常我们会将列表值存储在一个变量中</strong>，然后通过遍历变量的方式遍历了其内容的的列表。</p>
<p>看看怎么完成这个任务：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test3</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> using a variable to hold the list</span></span><br><span class="line">list="Alabama Alaska Arizona Arkansas Colorado"</span><br><span class="line">list=$list" Connecticut" # 在尾部拼接文本</span><br><span class="line"></span><br><span class="line">for state in $list; do</span><br><span class="line">  echo "Have you ever visited $state?"</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test3</span><br><span class="line">Have you ever visited Alabama?</span><br><span class="line">Have you ever visited Alaska?</span><br><span class="line">Have you ever visited Arizona?</span><br><span class="line">Have you ever visited Arkansas?</span><br><span class="line">Have you ever visited Colorado?</span><br><span class="line">Have you ever visited Connecticut?</span><br></pre></td></tr></table></figure>
<p>注意，代码中还用了另一个赋值语句向<code>$list</code>变量包含的已有列表中添加了一个值。这是在已有文本字符串尾部添加文本的一种常用方法。</p>
<p>我们还可以<strong>用命令来输出我们需要的列表内容</strong>：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test4</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> reading values from a file</span></span><br><span class="line"></span><br><span class="line">file="states"</span><br><span class="line"></span><br><span class="line">for state in $(cat $file)</span><br><span class="line">do</span><br><span class="line">    echo "Visit beautiful $state"</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat states</span><br><span class="line">Alabama</span><br><span class="line">Alaska</span><br><span class="line">Arizona</span><br><span class="line">Arkansas</span><br><span class="line">Colorado</span><br><span class="line">Connecticut</span><br><span class="line">Delaware</span><br><span class="line">Florida</span><br><span class="line">Georgia</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test4</span><br><span class="line">Visit beautiful Alabama</span><br><span class="line">Visit beautiful Alaska</span><br><span class="line">Visit beautiful Arizona</span><br><span class="line">Visit beautiful Arkansas</span><br><span class="line">Visit beautiful Colorado</span><br><span class="line">Visit beautiful Connecticut</span><br><span class="line">Visit beautiful Delaware</span><br><span class="line">Visit beautiful Florida</span><br><span class="line">Visit beautiful Georgia</span><br></pre></td></tr></table></figure>
<p><strong>更改字段分隔符</strong></p>
<p>环境变量<code>IFS</code>，也叫作字段分隔符。它定义了bash shell用作字段分隔符的一系列字符。默认情况下，bash shell会将<strong>空格、制表符和换行符</strong>当作字段分隔符。</p>
<p>如果想修改<code>IFS</code>的值，比如使其只能识别换行符，我们可以将下面这行代码加入脚本：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">IFS=$'\n'</span><br></pre></td></tr></table></figure>
<p>在处理大量脚本时，我们可能只在某一部分使用其他的分隔符，这时候可以先保存原有的<code>IFS</code>值，然后修改，最后恢复：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">IFS.OLD=$IFS</span><br><span class="line">IFS=$'\n'</span><br><span class="line">&lt;在代码中使用新的IFS值&gt;</span><br><span class="line">IFS=$IFS.OLD</span><br></pre></td></tr></table></figure>
<p>假如我们要遍历一个文件中用冒号分隔的值：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">IFS=:</span><br></pre></td></tr></table></figure>
<p>假如要指定多个<code>IFS</code>字符，只要将它们的赋值行串起来：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">IFS=$'\n':;"</span><br></pre></td></tr></table></figure>
<p>这个赋值会将换行符、冒号、分号以及双引号作为字段分隔符。</p>
<p><strong>用通配符读取目录</strong></p>
<p>我们可以用<code>for</code>命令来自动遍历目录中的文件。进行此操作时，必须在文件名或路径名中使用通配符。它会强制shell使用<strong>文件扩展匹配</strong>。文件扩展匹配是生成匹配指定通配符的文件名或路径名的过程。</p>
<p>我拿我的一个目录来尝试一下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test5</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> iterate through all the files <span class="keyword">in</span> a directory</span></span><br><span class="line"></span><br><span class="line">for file in /home/wsx/python_learn/*</span><br><span class="line">do</span><br><span class="line">  if [ -d "$file" ]</span><br><span class="line">  then</span><br><span class="line">    echo "$file is a directory"</span><br><span class="line">  elif [ -f "$file" ]</span><br><span class="line">  then</span><br><span class="line">    echo "$file is a file"</span><br><span class="line">  fi</span><br><span class="line">done</span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test5</span><br><span class="line">/home/wsx/python_learn/athletelist.py is a file</span><br><span class="line">/home/wsx/python_learn/athletemodel.py is a file</span><br><span class="line">/home/wsx/python_learn/ch2_data_input.py is a file</span><br><span class="line">/home/wsx/python_learn/chapter5_first.py is a file</span><br><span class="line">/home/wsx/python_learn/chapter6_first.py is a file</span><br><span class="line">/home/wsx/python_learn/chapter6_second.py is a file</span><br><span class="line">/home/wsx/python_learn/chapter6_third.py is a file</span><br><span class="line">/home/wsx/python_learn/coinFlips.py is a file</span><br><span class="line">/home/wsx/python_learn/Dive_into_python is a directory</span><br></pre></td></tr></table></figure>
<p><strong>注意：</strong>第一个方括号之后和第二个方括号之前必须加上一个空格，否则会报错。</p>
<p>在Linux中，目录名和文件名中包含空格是合法的，所以将<code>$file</code>变量用双引号圈起来。当然，大家尽量不要让文件或目录包含空格，不然很容易出问题（命令会把空格当做文件的分隔符）。</p>
<h3 id="C语言风格的for命令"><a href="#C语言风格的for命令" class="headerlink" title="C语言风格的for命令"></a>C语言风格的for命令</h3><p>C语言风格的<code>for</code>命令看起来如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">for (( a = 1; a &lt; 10; a++ ))</span><br></pre></td></tr></table></figure>
<p>值得注意的是，这里有些部分没有遵循bash shell标准的<code>for</code>命令：</p>
<ul>
<li>变量赋值可以有空格；</li>
<li>条件中的变量不以美元符开头；</li>
<li>迭代过程的算式未用<code>expr</code>命令格式。</li>
</ul>
<p>在使用这种格式时要小心，不同的格式不注意就会出错。</p>
<p>下面举个例子：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">wsx@wsx-ubuntu:~/script_learn$ cat test6</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> testing the C-style <span class="keyword">for</span> loop</span></span><br><span class="line"></span><br><span class="line">for (( i=1; i &lt;= 10; i++ ))</span><br><span class="line">do</span><br><span class="line">  echo "The next number is $i"</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wsx@wsx-ubuntu:~/script_learn$ ./test6</span><br><span class="line">The next number is 1</span><br><span class="line">The next number is 2</span><br><span class="line">The next number is 3</span><br><span class="line">The next number is 4</span><br><span class="line">The next number is 5</span><br><span class="line">The next number is 6</span><br><span class="line">The next number is 7</span><br><span class="line">The next number is 8</span><br><span class="line">The next number is 9</span><br><span class="line">The next number is 10</span><br></pre></td></tr></table></figure>
<h3 id="while命令"><a href="#while命令" class="headerlink" title="while命令"></a>while命令</h3><p><code>while</code>命令的格式为：<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">while test command</span><br><span class="line">do</span><br><span class="line">  other commands</span><br><span class="line">done</span><br></pre></td></tr></table></figure></p>
<p><code>while</code>命令某种意义上是<code>if-then</code>语句和<code>for</code>循环的混杂体。注意，这里<code>while</code>后面接的也是命令。<code>while</code>命令允许定义一个要测试的命令，然后循环执行一组命令，只要定义的测试命令返回的是退出状态码是0（类似一般语言中 的TRUE）。直到非0时退出循环。</p>
<p><code>while</code>命令中定义的<code>test command</code>和<code>if-then</code>语句中的格式一模一样。可以使用任何普通的bash shell命令，或者用<code>test</code>命令进行条件测试，比如测试变量值。</p>
<p>最常见的用法是用方括号来检查循环命令中用到的<code>shell</code>变量的值。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">wangsx@SC-201708020022:~/tmp$ cat test</span><br><span class="line"><span class="meta">#</span><span class="bash">/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> <span class="keyword">while</span> <span class="built_in">command</span> <span class="built_in">test</span></span></span><br><span class="line"></span><br><span class="line">var1=10</span><br><span class="line">while [ $var1 -gt 0 ]</span><br><span class="line">do</span><br><span class="line">        echo $var1</span><br><span class="line">        var1=$[ $var1 - 1 ]</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wangsx@SC-201708020022:~/tmp$ ./test</span><br><span class="line">10</span><br><span class="line">9</span><br><span class="line">8</span><br><span class="line">7</span><br><span class="line">6</span><br><span class="line">5</span><br><span class="line">4</span><br><span class="line">3</span><br><span class="line">2</span><br><span class="line">1</span><br></pre></td></tr></table></figure>
<p><strong>使用多个测试命令</strong><br><code>while</code>命令允许我们在<code>while</code>语句行中定义多个测试命令。只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环。<br>比如<code>while echo $var1 [ $var1 -ge 0 ]</code>检测的就是后面方括号命令的退出状态码。</p>
<h3 id="until命令"><a href="#until命令" class="headerlink" title="until命令"></a>until命令</h3><p><code>until</code>命令和<code>while</code>命令工作的方式完全相反。只有测试命令的退出状态码不为0，bash shell才会执行循环中列出的命令。一旦测试命令返回了退出状态码0，循环就结束了。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">until test command</span><br><span class="line">do</span><br><span class="line">  other commands</span><br><span class="line">done</span><br></pre></td></tr></table></figure>
<p>一个例子：<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">wangsx@SC-201708020022:~/tmp$ cat test12</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> using the until <span class="built_in">command</span></span></span><br><span class="line"></span><br><span class="line">var1=100</span><br><span class="line"></span><br><span class="line">until [ $var1 -eq 0 ]</span><br><span class="line">do</span><br><span class="line">        echo $var1</span><br><span class="line">        var1=$[ $var1 - 25 ]</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wangsx@SC-201708020022:~/tmp$ ./test12</span><br><span class="line">100</span><br><span class="line">75</span><br><span class="line">50</span><br><span class="line">25</span><br></pre></td></tr></table></figure></p>
<p>同样地，在<code>until</code>命令中放入多个测试命令时也要注意（类似<code>while</code>）。</p>
<h3 id="嵌套循环"><a href="#嵌套循环" class="headerlink" title="嵌套循环"></a>嵌套循环</h3><p>在循环语句内使用任意类型的命令，包括其他循环命令，叫做嵌套循环。因为是在迭代中迭代，需要注意变量的使用以及程序的效率问题。</p>
<p>下面举一个<code>for</code>循环嵌套<code>for</code>循环的例子：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">wangsx@SC-201708020022:~/tmp$ cat test14</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> nesting <span class="keyword">for</span> loops</span></span><br><span class="line"></span><br><span class="line">for (( a = 1; a &lt;= 3; a++ ))</span><br><span class="line">do</span><br><span class="line">        echo "Starting loop $a:"</span><br><span class="line">        for (( b = 1; b &lt;= 3; b++ ))</span><br><span class="line">        do</span><br><span class="line">                echo "    Inside loop: $b"</span><br><span class="line">        done</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wangsx@SC-201708020022:~/tmp$ . test14</span><br><span class="line">Starting loop 1:</span><br><span class="line">    Inside loop: 1</span><br><span class="line">    Inside loop: 2</span><br><span class="line">    Inside loop: 3</span><br><span class="line">Starting loop 2:</span><br><span class="line">    Inside loop: 1</span><br><span class="line">    Inside loop: 2</span><br><span class="line">    Inside loop: 3</span><br><span class="line">Starting loop 3:</span><br><span class="line">    Inside loop: 1</span><br><span class="line">    Inside loop: 2</span><br><span class="line">    Inside loop: 3</span><br></pre></td></tr></table></figure>
<p>shell能够自动识别匹配的<code>do</code>和<code>done</code>字符。这种模式很常见，比如通常的小括号（<code>(</code>与<code>)</code>）、中括号、花括号匹配等等。它们的本质都是字符匹配。</p>
<p>在混用循环命令时也一样，比如在<code>while</code>循环中内嵌一个<code>for</code>循环：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">wangsx@SC-201708020022:~/tmp$ cat test15</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> placing a <span class="keyword">for</span> loop inside a <span class="keyword">while</span> loop</span></span><br><span class="line"></span><br><span class="line">var1=5</span><br><span class="line"></span><br><span class="line">while [ $var1 -ge 0 ]</span><br><span class="line">do</span><br><span class="line">        echo "Outer loop: $var1"</span><br><span class="line">        for (( var2 = 1; $var2 &lt; 3; var2++))</span><br><span class="line">        do</span><br><span class="line">                var3=$[ $var1 * $var2 ]</span><br><span class="line">                echo "  Inner loop: $var1 * $var2 = $var3"</span><br><span class="line">        done</span><br><span class="line">        var1=$[ $var1 - 1 ]</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wangsx@SC-201708020022:~/tmp$ . test15</span><br><span class="line">Outer loop: 5</span><br><span class="line">  Inner loop: 5 * 1 = 5</span><br><span class="line">  Inner loop: 5 * 2 = 10</span><br><span class="line">Outer loop: 4</span><br><span class="line">  Inner loop: 4 * 1 = 4</span><br><span class="line">  Inner loop: 4 * 2 = 8</span><br><span class="line">Outer loop: 3</span><br><span class="line">  Inner loop: 3 * 1 = 3</span><br><span class="line">  Inner loop: 3 * 2 = 6</span><br><span class="line">Outer loop: 2</span><br><span class="line">  Inner loop: 2 * 1 = 2</span><br><span class="line">  Inner loop: 2 * 2 = 4</span><br><span class="line">Outer loop: 1</span><br><span class="line">  Inner loop: 1 * 1 = 1</span><br><span class="line">  Inner loop: 1 * 2 = 2</span><br><span class="line">Outer loop: 0</span><br><span class="line">  Inner loop: 0 * 1 = 0</span><br><span class="line">  Inner loop: 0 * 2 = 0</span><br></pre></td></tr></table></figure>
<p>如果想要挑战脑力，可以混用<code>until</code>和<code>while</code>循环。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">wangsx@SC-201708020022:~/tmp$ cat test16</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> using until and <span class="keyword">while</span> loop</span></span><br><span class="line"></span><br><span class="line">var1=3</span><br><span class="line"></span><br><span class="line">until [ $var1 -eq 0 ]</span><br><span class="line">do</span><br><span class="line">        echo "Outer loop: $var1"</span><br><span class="line">        var2=1</span><br><span class="line">        while [ $var2 -lt 5 ]</span><br><span class="line">        do</span><br><span class="line">                var3=$(echo "scale=4; $var1 / $var2" | bc)</span><br><span class="line">                echo "  Inner loop: $var1 / $var2 = $var3"</span><br><span class="line">                var2=$[ $var2 + 1 ]</span><br><span class="line">        done</span><br><span class="line">        var1=$[ $var1 - 1 ]</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">wangsx@SC-201708020022:~/tmp$ . test16</span><br><span class="line">Outer loop: 3</span><br><span class="line">  Inner loop: 3 / 1 = 3.0000</span><br><span class="line">  Inner loop: 3 / 2 = 1.5000</span><br><span class="line">  Inner loop: 3 / 3 = 1.0000</span><br><span class="line">  Inner loop: 3 / 4 = .7500</span><br><span class="line">Outer loop: 2</span><br><span class="line">  Inner loop: 2 / 1 = 2.0000</span><br><span class="line">  Inner loop: 2 / 2 = 1.0000</span><br><span class="line">  Inner loop: 2 / 3 = .6666</span><br><span class="line">  Inner loop: 2 / 4 = .5000</span><br><span class="line">Outer loop: 1</span><br><span class="line">  Inner loop: 1 / 1 = 1.0000</span><br><span class="line">  Inner loop: 1 / 2 = .5000</span><br><span class="line">  Inner loop: 1 / 3 = .3333</span><br><span class="line">  Inner loop: 1 / 4 = .2500</span><br></pre></td></tr></table></figure>
<p>外部的<code>until</code>循环以值3开始，并继续执行到值等于0。内部<code>while</code>循环以值1开始一直执行，只要值小于5。需要注意循环条件的设置，我跑的几次都没写完整，然后无限循环只好重开终端。</p>
<h3 id="控制循环"><a href="#控制循环" class="headerlink" title="控制循环"></a>控制循环</h3><p>之前的学的命令已经可以让我们写循环程序了，设定好以后等待命令开始执行和等待循环结束。但是很多情况下，在循环中我们设定的某个（多个）变量达到某种条件时，我们就想要停止循环，然后运行循环下面的命令。这时候我们需要用到<code>break</code>和<code>continue</code>命令来帮我们控制住循环。</p>
<p>这两个命令在其他语言中基本都时关键字，特别是<code>C</code>，用法差不多。我也就不具体介绍了，只点出它们的功能。</p>
<p><strong>break</strong></p>
<blockquote>
<p>在shell执行break命令时，它会尝试跳出当前正在执行的循环。</p>
<p>在处理多个循环时，break命令会自动终止你所在的最内层循环。</p>
<p>break命令接受单个命令行参数值：</p>
<p>​    break n</p>
<p>​    其中n制订了要跳出的循环层级（层数）</p>
</blockquote>
<p><strong>continue</strong></p>
<blockquote>
<p>continue命令可以提前终止某次循环的命令，但并不会完全终止整个循环。可以在循环内部设置shell不执行命令的条件。</p>
<p>也就是说使用continue命令时，它会自动跳过本次循环中接下来的运行步骤，跳转到下一次循环。但注意不是跳出，跳出时break的功能。</p>
<p>同样的可以使用continue n         n制定要继续执行哪一级循环</p>
</blockquote>
<h3 id="处理循环的输出"><a href="#处理循环的输出" class="headerlink" title="处理循环的输出"></a>处理循环的输出</h3><p>在shell脚本中，我们可以对循环的输出使用管道或进行重定向。这是通过在<code>done</code>命令之后添加一个处理命令来实现的。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">wangsx@SC-201708020022:~/tmp$ cat test</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line">for file in /home/*</span><br><span class="line">do</span><br><span class="line">        if [ -d "$file" ]</span><br><span class="line">        then</span><br><span class="line">                echo "$file is a directory"</span><br><span class="line">        else</span><br><span class="line">                echo "$file is a file"</span><br><span class="line">        fi</span><br><span class="line">done &gt; output.txt</span><br><span class="line">wangsx@SC-201708020022:~/tmp$ cat output.txt</span><br><span class="line">/home/wangsx is a directory</span><br></pre></td></tr></table></figure>
<p>shell将<code>for</code>命令的结果重定向到文件<code>output.txt</code>中，而不是显示在屏幕上。</p>
<h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><p>下面两个例子演示如何用简单循环来处理数据。</p>
<p><strong>查找可执行文件</strong></p>
<p>Linux运行程序时通过环境变量<code>$PATH</code>提供的目录搜索可执行文件。如果徒手找的话，比较费时间，我们可以写个脚本来搞定它。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">wangsx@SC-201708020022:~$ cat test25</span><br><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> finding files <span class="keyword">in</span> the PATH</span></span><br><span class="line"></span><br><span class="line">IFS=:</span><br><span class="line">for folder in $PATH</span><br><span class="line">do</span><br><span class="line">        echo "$folder:"</span><br><span class="line">        for file in $folder/*</span><br><span class="line">        do</span><br><span class="line">                if [ -x $file ]</span><br><span class="line">                then</span><br><span class="line">                        echo "  $file"</span><br><span class="line">                fi</span><br><span class="line">        done</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 输出结果太多，我就不拷贝结果了</span></span><br></pre></td></tr></table></figure>
<p>先设定<code>IFS</code>分隔符以便于能正确分隔目录，然后将目录存放在<code>$folder</code>中，用<code>for</code>循环来迭代特定的目录中所有文件，然后用<code>if-then</code>命令检查文件的可执行权限。</p>
<p>Linux有一个<code>tree</code>工具，非常方便输出目录结构，推荐使用下。</p>
<p><strong>创建多个用户账号</strong></p>
<p>如果你是管理员，需要创建大量账号时。不必每次都有<code>useradd</code>命令添加用户。将用户信息存放在指定文件，然后用脚本进行处理就可以了。</p>
<p>用户信息的格式如下：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">userid,<span class="built_in"> user </span>name</span><br></pre></td></tr></table></figure>
<p>第一个是你为用户选择的id，第二个是用户的全名。这是<code>csv</code>文件格式。</p>
<p>为了能够读取它，我们使用以下命令：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">while IFS=',' read -r userid name</span><br></pre></td></tr></table></figure>
<p><code>read</code>命令会自动获取<code>.csv</code>文本文件的下一行内容，所以不用再写一个循环来处理。当<code>read</code>命令返回<code>FALSE</code>时（也就是读完了），<code>while</code>命令就会退出。</p>
<p>为了把数据从文件导向<code>while</code>命令，只要再<code>while</code>命令尾部加一个重定向符号。</p>
<p>处理过程写成脚本如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> process new user accounts</span></span><br><span class="line"></span><br><span class="line">input="users.csv"</span><br><span class="line">while IFS=',', read -r userid name</span><br><span class="line">do</span><br><span class="line">trueecho "adding $userid"</span><br><span class="line">trueuseradd -c "$name" -m $userid</span><br><span class="line">done &lt; "$input"</span><br></pre></td></tr></table></figure>

      
    </div>
    
  </div>
  
    
    <div class="copyright">
        <p><span>本文标题:</span><a href="">Linux结构化命令</a></p>
        <!-- modify author information
        <p><span>文章作者:</span><a href="/" title="回到主页">王诗翔</a></p>
        -->
        <p><span>文章作者:</span>王诗翔</p>
        <p><span>发布时间:</span>2017-08-11, 00:00:00</p>
        <p><span>最后更新:</span>2018-01-27, 12:08:05</p>
        <p>
            <span>原始链接:</span><a class="post-url" href="" title="Linux结构化命令">https://shixiangwang.github.io/2017/08/11/structural-command-of-shell/</a>
            <span class="copy-path" data-clipboard-text="原文: https://shixiangwang.github.io/2017/08/11/structural-command-of-shell/　　作者: 王诗翔" title="点击复制文章链接"><i class="fa fa-clipboard"></i></span>
            <script> var clipboard = new Clipboard('.copy-path'); </script>
        </p>
        <p>
            <span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" title="CC BY-NC-SA 4.0 International" target = "_blank">"署名-非商用-相同方式共享 4.0"</a> 转载请保留原文链接及作者。
        </p>
    </div>



    <nav id="article-nav">
        
            <div id="article-nav-newer" class="article-nav-title">
                <a href="../../19/working-with-user-input/">
                    Shell脚本之处理用户输入
                </a>
            </div>
        
        
            <div id="article-nav-older" class="article-nav-title">
                <a href="../basic-shell/">
                    构建基本shell脚本
                </a>
            </div>
        
    </nav>


  
</article>

    <div id="toc" class="toc-article">
        <strong class="toc-title">文章目录</strong>
        
            <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#条件控制"><span class="toc-number">1.</span> <span class="toc-text">条件控制</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#if-then语句"><span class="toc-number">1.1.</span> <span class="toc-text">if-then语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#if-then-else语句"><span class="toc-number">1.2.</span> <span class="toc-text">if-then-else语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#嵌套if"><span class="toc-number">1.3.</span> <span class="toc-text">嵌套if</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#test命令"><span class="toc-number">1.4.</span> <span class="toc-text">test命令</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#复合条件测试"><span class="toc-number">1.5.</span> <span class="toc-text">复合条件测试</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#if-then的高级特性"><span class="toc-number">1.6.</span> <span class="toc-text">if-then的高级特性</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#case命令"><span class="toc-number">1.7.</span> <span class="toc-text">case命令</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#小结"><span class="toc-number">1.8.</span> <span class="toc-text">小结</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#循环控制"><span class="toc-number">2.</span> <span class="toc-text">循环控制</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#for命令"><span class="toc-number">2.1.</span> <span class="toc-text">for命令</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#C语言风格的for命令"><span class="toc-number">2.2.</span> <span class="toc-text">C语言风格的for命令</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#while命令"><span class="toc-number">2.3.</span> <span class="toc-text">while命令</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#until命令"><span class="toc-number">2.4.</span> <span class="toc-text">until命令</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#嵌套循环"><span class="toc-number">2.5.</span> <span class="toc-text">嵌套循环</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#控制循环"><span class="toc-number">2.6.</span> <span class="toc-text">控制循环</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#处理循环的输出"><span class="toc-number">2.7.</span> <span class="toc-text">处理循环的输出</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#实例"><span class="toc-number">2.8.</span> <span class="toc-text">实例</span></a></li></ol></li></ol>
        
    </div>
    <style>
        .left-col .switch-btn,
        .left-col .switch-area {
            display: none;
        }
        .toc-level-3 i,
        .toc-level-3 ol {
            display: none !important;
        }
    </style>

    <input type="button" id="tocButton" value="隐藏目录"  title="点击按钮隐藏或者显示文章目录">

    <script>
        yiliaConfig.toc = ["隐藏目录", "显示目录", !!"false"];
    </script>



    
<div class="share">
    
        <div class="bdsharebuttonbox">
            <a href="#" class="fa fa-twitter bds_twi" data-cmd="twi" title="分享到推特"></a>
            <a href="#" class="fa fa-weibo bds_tsina" data-cmd="tsina" title="分享到新浪微博"></a>
            <a href="#" class="fa fa-qq bds_sqq" data-cmd="sqq" title="分享给 QQ 好友"></a>
            <a href="#" class="fa fa-files-o bds_copy" data-cmd="copy" title="复制网址"></a>
            <a href="#" class="fa fa fa-envelope-o bds_mail" data-cmd="mail" title="通过邮件分享"></a>
            <a href="#" class="fa fa-weixin bds_weixin" data-cmd="weixin" title="生成文章二维码"></a>
            <a href="#" class="fa fa-share-alt bds_more" data-cmd="more"></i></a>
        </div>
        <script>
            window._bd_share_config={
                "common":{"bdSnsKey":{},"bdText":"Linux结构化命令　| Cloudberry　","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"24"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
        </script>
    

    
</div>







    
        <section id="comments">
    <style> aside.comment-bar { margin: auto 30px; }</style>
    <div id="disqus_thread"></div>
    <script>
        var disqus_config = function(){
            this.page.url = 'https://shixiangwang.github.io/2017/08/11/structural-command-of-shell/';
            this.page.identifier = '2017/08/11/structural-command-of-shell/';
        };
        var loadComment = function(){
            var d = document, s = d.createElement('script');
            s.src = '//Cloudberry.disqus.com/embed.js';
            s.setAttribute('data-timestamp', +new Date());
            (d.head || d.body).appendChild(s);
        }
    </script>
    
    <script> loadComment(); </script>

</section>


    




    <div class="scroll" id="post-nav-button">
        
            <a href="../../19/working-with-user-input/" title="上一篇: Shell脚本之处理用户输入">
                <i class="fa fa-angle-left"></i>
            </a>
        

        <a title="文章列表"><i class="fa fa-bars"></i><i class="fa fa-times"></i></a>

        
            <a href="../basic-shell/" title="下一篇: 构建基本shell脚本">
                <i class="fa fa-angle-right"></i>
            </a>
        
    </div>

    <ul class="post-list"><li class="post-list-item"><a class="post-list-link" href="../../../../2018/02/26/python-basics/">两天研习Python基础</a></li><li class="post-list-item"><a class="post-list-link" href="../../../../2018/02/12/how-to-create-an-independent-figpath/">为markdown博文创建独立图片路径</a></li><li class="post-list-item"><a class="post-list-link" href="../../../../2018/02/10/easy-sapply-apply-vapply/">简单理解lapply,sapply,vapply</a></li><li class="post-list-item"><a class="post-list-link" href="../../../../2018/02/07/how-to-do-group-survival-analysis/">怎么对连续变量分组并进行生存分析</a></li><li class="post-list-item"><a class="post-list-link" href="../../../../2018/02/06/how-to-write-rmd-documents-in-hexo-system/">怎么在hexo博客系统中用Rmarkdown写文章</a></li><li class="post-list-item"><a class="post-list-link" href="../../../../2018/01/31/sed-how-to-filter-rows-before-using-command/">sed如何在执行命令前过滤特定文本行</a></li><li class="post-list-item"><a class="post-list-link" href="../../../../2018/01/31/sync-deploy-tools/">Sync deploy 命令工具</a></li><li class="post-list-item"><a class="post-list-link" href="../../../12/25/sed-and-gawk/">初识sed与awk</a></li><li class="post-list-item"><a class="post-list-link" href="../../../12/08/Git-basic-operation/">学习git</a></li><li class="post-list-item"><a class="post-list-link" href="../../../11/29/shell-create-text-menu-and-window/">使用shell创建文本菜单和窗口部件</a></li><li class="post-list-item"><a class="post-list-link" href="../../../11/26/shell-create-function/">创建和使用shell函数</a></li><li class="post-list-item"><a class="post-list-link" href="../../../09/20/OOPinR/">R-面向对象编程</a></li><li class="post-list-item"><a class="post-list-link" href="../../../09/15/Class-in-R/">R中的属性与类</a></li><li class="post-list-item"><a class="post-list-link" href="../../../09/04/control_shell/">控制脚本</a></li><li class="post-list-item"><a class="post-list-link" href="../../../09/03/Linux-data-analysis-tools/">Linux数据处理命令工具</a></li><li class="post-list-item"><a class="post-list-link" href="../../21/shell-show-data/">Linux脚本编程——呈现数据</a></li><li class="post-list-item"><a class="post-list-link" href="../../19/working-with-user-input/">Shell脚本之处理用户输入</a></li><li class="post-list-item"><a class="post-list-link" href="">Linux结构化命令</a></li><li class="post-list-item"><a class="post-list-link" href="../basic-shell/">构建基本shell脚本</a></li></ul>




    <script>
        
    </script>
</div>
      <footer id="footer">
    <div class="outer">
        <div id="footer-info">
            <div class="footer-left">
                <i class="fa fa-copyright"></i> 
                2017-2018 王诗翔
            </div>
            <div class="footer-right">
                <a href="http://hexo.io/" target="_blank" title="快速、简洁且高效的博客框架">Hexo</a>  Theme <a href="https://github.com/MOxFIVE/hexo-theme-yelee" target="_blank" title="简而不减 Hexo 双栏博客主题  v3.5">Yelee</a> by MOxFIVE <i class="fa fa-heart animated infinite pulse"></i>
            </div>
        </div>
        
            <div class="visit">
                
                    <span id="busuanzi_container_site_pv" style='display:none'>
                        <span id="site-visit" title="本站到访数"><i class="fa fa-user" aria-hidden="true"></i><span id="busuanzi_value_site_uv"></span>
                        </span>
                    </span>
                
                
                    <span>| </span>
                
                
                    <span id="busuanzi_container_page_pv" style='display:none'>
                        <span id="page-visit"  title="本页阅读量"><i class="fa fa-eye animated infinite pulse" aria-hidden="true"></i><span id="busuanzi_value_page_pv"></span>
                        </span>
                    </span>
                
            </div>
        
    </div>
</footer>
    </div>
    
    <script src="../../../../js/GithubRepoWidget.js"></script>

<script data-main="/js/main.js" src="//cdn.bootcss.com/require.js/2.2.0/require.min.js"></script>

    <script>
        $(document).ready(function() {
            var iPad = window.navigator.userAgent.indexOf('iPad');
            if (iPad > -1 || $(".left-col").css("display") === "none") {
                var bgColorList = ["#9db3f4", "#414141", "#e5a859", "#f5dfc6", "#c084a0", "#847e72", "#cd8390", "#996731"];
                var bgColor = Math.ceil(Math.random() * (bgColorList.length - 1));
                $("body").css({"background-color": bgColorList[bgColor], "background-size": "cover"});
            }
            else {
                var backgroundnum = 2;
                var backgroundimg = "url(/background/bg-x.jpg)".replace(/x/gi, Math.ceil(Math.random() * backgroundnum));
                $("body").css({"background": backgroundimg, "background-attachment": "fixed", "background-size": "cover"});
            }
        })
    </script>





    <script type="text/x-mathjax-config">
MathJax.Hub.Config({
    tex2jax: {
        inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
        processEscapes: true,
        skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
    }
});

MathJax.Hub.Queue(function() {
    var all = MathJax.Hub.getAllJax(), i;
    for(i=0; i < all.length; i += 1) {
        all[i].SourceElement().parentNode.className += ' has-jax';                 
    }       
});
</script>

<script src="//cdn.bootcss.com/mathjax/2.6.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>


<div class="scroll" id="scroll">
    <a href="#" title="返回顶部"><i class="fa fa-arrow-up"></i></a>
    <a href="#comments" onclick="load$hide();" title="查看评论"><i class="fa fa-comments-o"></i></a>
    <a href="#footer" title="转到底部"><i class="fa fa-arrow-down"></i></a>
</div>
<script>
    // Open in New Window
    
        var oOpenInNew = {
             github: ".github-widget a", 
            
             post: ".article-entry a[href], .copyright a[href]", 
            
            
            
             archives: ".archive-article-title", 
             miniArchives: "a.post-list-link", 
            
             friends: "#js-friends a", 
             socail: ".social a" 
        }
        for (var x in oOpenInNew) {
            $(oOpenInNew[x]).attr("target", "_blank");
        }
    
</script>

    <script>
        var originTitle = document.title;
        var titleTime;
        document.addEventListener("visibilitychange", function() {
            if (document.hidden) {
                document.title = "(つェ⊂) 我藏好了哦~ " + originTitle;
                clearTimeout(titleTime);
            }
            else {
                document.title = "(*´∇｀*) 被你发现啦~ " + originTitle;
                titleTime = setTimeout(function() {
                    document.title = originTitle;
                }, 2000);
            }
        })
    </script>

<script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js">
</script>
  </div>
</body>
</html>